package cn.learn.generator.controller;

import cn.learn.utils.desensitization.DesensitizationUtil;
import cn.learn.utils.random.RandomDateTimeUtil;
import cn.learn.utils.random.RandomIdCardUtil;
import cn.learn.utils.random.RandomNumUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author huangyezhan
 * @version 1.0
 * @date 2020年10月17日11:02
 */
@Slf4j
@RestController
@RequestMapping("/generator")
public class GeneratorController {

    /*
     {t_base_user:
        {total:10000,（生成数据的总条数）
         columns:[userName,idNo,age···],
            id: {name:id,type:seq},（seq为自增顺序,uuid为uuid去掉-）

            userName: {name:"name",type:"1"}, (1全名; 2脱敏名字)
            idNo: {name:"idNo",type:"1"},（1身份证号码; 2脱敏）
            age: {name:"birth",type:"",min:"1989-01-01",max:"2020-10-19"},(年龄为整数 1-99)
            gender: {name:"option",type:[1,2]},(自定义选项)
            gender: {
                name:"option",
                columns:[{code:"1",name:"男"}],
                selected:[code,name]         （选中的选项）
            },(自定义选项)
            address: {name:"address",type:"1"},(1地址;2脱敏)

            idCard: {
                name:"idCard",
                columns:{
                    userName: {name:"name",type:"1"},
                    idNo: {name:"idNo",type:"1"},
                    age: {name:"birth",type:"",min:"1989-01-01",max:"2020-10-19"},
                    gender: {name:"option",type:[1,2]},
                    address: {name:"address",type:"1"}
                }
            },（idCard包括上面5项）

            price: {name:"double",min:0.00,max:128.11,format:"#.00"},（大、小、格式）
            type: {name:"int",min:0,max:22},(整数大、小)
            date: {name:"datetime",min:"1989-01-01 14:23:53",max:"2020-10-19 14:23:53",format:"yyyyMMddd HH:mm:ss"}(时间大、小、格式)
        }
     }
     */

    /**
     * key为需要生成对象的名称；value为数据类型的标识
     * 第一层为 表名称 t_base_user
     * 第二次为 表的类类型标识
     *
     * @param map 需要生成的数据选项，数据结构如上所示
     */
    @RequestMapping(method = RequestMethod.POST)
    public List generator(@RequestBody Map<String, Object> map) {

        System.out.println(Thread.currentThread().getId());
        String name = Thread.currentThread().getName();
        System.out.println(name);
        Thread.currentThread().setName("update_thread");
        System.out.println(name + ":" + Thread.currentThread().getName());

        long start = System.currentTimeMillis();
        for (String key : map.keySet()) {
            //第二层(单表 所有属性)
            Map<String, Object> o         = (Map<String, Object>) map.get(key);
            Integer             total     = (Integer) o.get("total");
            List<String>        columns   = (List<String>) o.get("columns");
            String              sqlPrefix = creatInsertSql(key, new HashSet<>(columns));
            o.remove("total");
            o.remove("columns");

            List<Map<String, Object>> list  = new ArrayList<>();
            Map<String, Object>       table = null;
            for (int i = 0; i < total; i++) {
                table = new HashMap<>();
                list.add(table);

                for (String k : o.keySet()) {
                    Object data = generateData((Map<String, Object>) o.get(k));
                    if (data instanceof Map) {
                        Map<String, Object> d = (Map<String, Object>) data;
                        table.putAll(d);
                    } else {
                        table.put(k, data);
                    }
                }
            }
            System.out.println("耗时（ms）：" + (System.currentTimeMillis() - start));
            return list;
        }
        System.out.println("耗时（ms）：" + (System.currentTimeMillis() - start));
        return null;
    }

    /**
     * 创建插入sql
     * insert into t_base_user(id,name,age,address,gender) values(),()
     *
     * @param tableName 表名
     * @param columns   列明
     */
    private static String creatInsertSql(String tableName, Set<String> columns) {
        String columnStr = StringUtils.join(columns, ",");
        return "INSERT INTO " + tableName + " (" + columnStr + ")" + " VALUES ";
    }


    private static final Random RANDOM = new Random();
    private static final String TYPE   = "type";

    private static Object generateData(Map<String, Object> map) {
        String name = (String) map.get("name");
        switch (name) {
            case "id":
                return UUID.randomUUID().toString().replace("-", "");
            case "name":
                if ("2".equals(map.get(TYPE))) {
                    return RandomIdCardUtil.getRandomNameDesensitized();
                }
                return RandomIdCardUtil.getRandomName();
            case "idNo":
                String idNo = RandomIdCardUtil.getIdNo(RANDOM.nextBoolean());
                if ("2".equals(map.get(TYPE))) {
                    return DesensitizationUtil.idEncrypt(idNo);
                }
                return idNo;
            case "birth":
                return RandomIdCardUtil.getBirth("yyyy-MM-dd");
            case "address":
                return null;
            case "idCard":
                return getIdCard(map);
            case "option":
                List options = (List) map.get("columns");
                int nextInt = RANDOM.nextInt(options.size());
                Object o = options.get(nextInt);
                //选项是对象
                if (o instanceof Map) {
                    Map<String, Object> opt      = new HashMap<>();
                    Map<String, Object> option   = (Map<String, Object>) o;
                    List<String>        selected = (List<String>) map.get("selected");
                    for (String k : selected) {
                        opt.put(k, option.get(k));
                    }
                    return opt;
                }
                //选项是是单元素
                return o;
            case "double":
                String format = (String) map.get("format");
                String multiple = (String) map.get("multiple");
                if (multiple != null) {
                    return RandomNumUtil.getDouble(Integer.parseInt(multiple));
                }
                String min = (String) map.get("min");
                String max = (String) map.get("max");
                return RandomNumUtil.getDouble(Double.parseDouble(min), Double.parseDouble(max));
            case "int":
                String min2 = (String) map.get("min");
                String max2 = (String) map.get("max");
                if (min2 != null && max2 != null) {
                    return RandomNumUtil.getInteger(Integer.parseInt(min2), Integer.parseInt(max2));
                }
                if (min2 == null && max2 == null) {
                    return RandomNumUtil.getInteger();
                }
                return RandomNumUtil.getInteger(Integer.parseInt(min2));
            case "datetime":
                //date: {name:"datetime",min:"1989-01-01 14:23:53",max:"2020-10-19 14:23:53",format:"yyyyMMddd HH:mm:ss"}(时间大、小、格式)
                try {
                    String           format1 = (String) map.get("format");
                    SimpleDateFormat sdf     = new SimpleDateFormat(format1);
                    Date             start   = sdf.parse((String) map.get("min"));
                    Date             end     = sdf.parse((String) map.get("max"));
                    return RandomDateTimeUtil.getRandomDateTime(start, end, format1);
                } catch (ParseException e) {
                    log.info("时间格式转换异常：{}", e.getMessage());
                }

            default:
                return name;
        }
    }

    /* 身份证信息：姓名、出生日期、身份证编码、户籍地址
        idCard: {
            name:"idCard",
            columns:{
                userName: {name:"name",type:"1"},
                idNo: {name:"idNo",type:"1"},
                age: {name:"birth",type:"",min:"1989-01-01",max:"2020-10-19"},
                gender: {name:"option",type:[1,2]},
                address: {name:"address",type:"1"}
            }
        }
     */

    public static Map<String, Object> getIdCard(Map<String, Object> map) {
        Map<String, Object> card    = new HashMap<>();
        Map<String, Object> idCard  = RandomIdCardUtil.getRandomIdCard();
        Map<String, Object> columns = (Map<String, Object>) map.get("columns");
        for (String key : columns.keySet()) {
            Map<String, Object> column = (Map<String, Object>) columns.get(key);
            card.put(key, idCard.get(column.get("name")));
        }
        return card;
    }

    public static void main(String[] args) throws ParseException {
        Map<String, Object> map = new HashMap(16);
        map.put("name", "idNo");
        System.out.println(generateData(map));

        map.put("name", "birth");
        System.out.println(generateData(map));

        map.put("name", "double");
        //map.put("multiple", "6");
        map.put("min", "500.01");
        map.put("max", "600.01");
        System.out.println(generateData(map));

        map.put("name", "int");
        map.put("min", "500");
        map.put("max", "600");
        System.out.println(generateData(map));


        SimpleDateFormat sdf   = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date             start = sdf.parse("1989-01-01 14:23:53");
        Date             end   = sdf.parse("2020-10-19 14:23:53");
        map.put("name", "datetime");
        map.put("min", start);
        map.put("max", end);
        map.put("format", "yyyy-MM-dd HH:mm:ss");
        System.out.println(generateData(map));
    }

}
